// EditStep.cpp: implementation of the CEditStep class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ansieditor.h"
#include "EditStep.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CEditStep::CEditStep(CAnsiPage *pAnsiPage)
{
	m_pPage = pAnsiPage;
}

CEditStep::~CEditStep()
{
}

void CEditStep::SaveCursorPos(int x, int y)
{
	m_ptCursor.x = x;
	m_ptCursor.y = y;
}

void CEditStep::Restore()
{
	int n, nCount, x, y;
	// save cur cells first
	nCount = m_arrCellData.GetSize();
	if(!nCount)
	{
		return;
	}
	CellData *tarrCellData = new CellData[nCount];
	for(n = 0; n < nCount; n++)
	{
		CellData rCellData = m_arrCellData.GetAt(n);
		x = rCellData.pt.x;
		y = rCellData.pt.y;

		tarrCellData[n].c = m_pPage->m_chars[y][x];
		tarrCellData[n].cell = m_pPage->m_cells[y][x];
		tarrCellData[n].pt.x = x;
		tarrCellData[n].pt.y = y;
	}
	for(n = nCount - 1; n >= 0; n--)
	{
		CellData rCellData = m_arrCellData.GetAt(n);
		x = rCellData.pt.x;
		y = rCellData.pt.y;
		m_pPage->m_chars[y][x] = rCellData.c;
		m_pPage->m_cells[y][x] = rCellData.cell;
	}
	memcpy((LPBYTE)m_arrCellData.GetData(), tarrCellData, sizeof(CellData) * nCount);

	delete [] tarrCellData;
	CPoint ptCursor = GetAppContext()->m_pView->GetCaretPos();
	GetAppContext()->m_pView->SetCaretPos(m_ptCursor);
	m_ptCursor = ptCursor;
}

void CEditStep::AddCells(int x1, int y1, int x2, int y2)
{
	for(int y = y1; y <= y2; y++)
	{
		if(GetAppContext()->m_pDoc->IsGBKSecondByte(y, x1))
		{
			AddCell(x1 - 1, y);
		}
		for(int x = x1; x <= x2; x++)
		{
			AddCell(x, y);
		}
		if(GetAppContext()->m_pDoc->IsGBKFirstByte(y, x2))
		{
			AddCell(x2 + 1, y);
		}
	}
}

BOOL CEditStep::IsEmpty()
{
//	if(!this)
//	{
//		return FALSE;
//	}
	return (m_arrCellData.GetSize() == 0);
}

CRect CEditStep::GetAffectedRect()
{
	CRect rect(65535, 65535, 0, 0);
	for(int n = 0; n < m_arrCellData.GetSize(); n++)
	{
		CPoint pt = m_arrCellData.GetAt(n).pt;
		if(pt.x < rect.left) rect.left = pt.x;
		if(pt.x > rect.right) rect.right = pt.x;
		if(pt.y < rect.top) rect.top = pt.y;
		if(pt.y > rect.bottom) rect.bottom = pt.y;
	}
	return rect;
}

void CEditStep::Compact()
{
	CArray<int, int> arrIndexToRemove;
	int n, count = m_arrCellData.GetSize();
// 	int size0 = m_arrCellData.GetSize();
	CellData* pData = m_arrCellData.GetData();
	CRect rect = GetAffectedRect();
	int rw = rect.Width() + 1;
	int rh = rect.Height() + 1;
	CArray<BOOL, BOOL> arrCellFlag;
	arrCellFlag.SetSize(rw * rh);
	BOOL *pCellFlag = arrCellFlag.GetData();
	for(n = 0; n < count; n++)
	{
		const CPoint& pt = pData[n].pt;
		BOOL &flag = pCellFlag[(pt.y - rect.top) * rw + (pt.x - rect.left)];

		if(flag)
		{
			arrIndexToRemove.Add(n);
		}
		else
		{
			if( (pData[n].c == m_pPage->m_chars[pt.y][pt.x]) &&
				(pData[n].cell == m_pPage->m_cells[pt.y][pt.x]) )
			{
				arrIndexToRemove.Add(n);
			}
			flag = TRUE;
		}
	}
	count = arrIndexToRemove.GetSize();
	for(n = count - 1; n >= 0; n--)
	{
		int idx = arrIndexToRemove.GetAt(n);
		m_arrCellData.RemoveAt(idx);
	}
// 	int size1 = m_arrCellData.GetSize();
// 	if(size1 < size0)
// 	{
// 		Sleep(0);
// 	}
}